#include <stdio.h>
#include <winsock2.h>
#include "commom.h"

#pragma comment( lib, "ws2_32.lib" ) // linker must use this lib for sockets

#define MAX_PACKET_SIZE 1500

Queue_t g_QueueProcess, g_QueueComplete;
char g_strCurHost[HOST_MAX_LEN] = "";

void get_machine_ip(char *_retIP)
{
	char host_name[128];
	struct hostent *hs;
	struct in_addr in;
	
	memset( host_name, 0x00, sizeof(host_name) );
	gethostname(host_name,128);
	hs = gethostbyname(host_name);
	
	memcpy( &in, hs->h_addr, hs->h_length );
	strcpy( _retIP, inet_ntoa(in) );
	printf("host ip = %s\n", _retIP);
}

void translate_ip(DWORD _ip, char *_cip)
{
	struct in_addr in;
	
	in.S_un.S_addr = _ip;
	strcpy( _cip, inet_ntoa(in) );
}

int generate_filename_for_save(char *path, char *presult)
{
	char *pStart = NULL, *pDot = NULL;
	int i = 0;
	char buf[64] = "";

	if (NULL == presult || NULL == path)
	{
		printf("generate_filename_for_save:Null pointer\n");
		return -1;
	}

	for (i=strlen(path)-1; i>=0; i--)
	{
		if (path[i] == '.')
		{
			pDot = path + i;
		}
		if (path[i] == '/')
		{
			pStart = path + i;
			break;
		}
	}

	if (NULL == pStart)
	{
		printf("gerneate_filename_for_save:no / in path\n");
		return -1;
	}

	if (NULL == pDot)
	{
		printf("gerneate_filename_for_save:no . in path\n");
		return -1;
	}

	strcpy(presult, pStart+1);

	return 0;
}
int split_url_to_host_path(char *url, char *host, char *path)
{
	int len = 0;
	char *pHostS = url, *pPathS = NULL;

	if (NULL == url || NULL == host || NULL == path)
	{
		printf("split_url_to_host_path:Null pointer\n");
		return -1;
	}

	len = strlen(url);
	if((pHostS = strstr(url, "http://")) != NULL)
	{
		pHostS += strlen("http://");
	}
	else
	{
		pHostS = url;
	}

	if((pPathS = strstr(pHostS, "/")) != NULL)
	{
		//pPathS += strlen("/");
	}
	else
	{
		pPathS = pHostS;
	}

	if (pPathS == pHostS)
	{
		return -1;
	}

	strncpy(host, pHostS, pPathS-pHostS);
	strcpy(path, pPathS);
	return 0;
}

#define URL_START_STR "<a href="
#define URL_START_LEN (strlen(URL_START_STR)+1)
#define HTTP_START_STR "http://"
int parse_url_from_http_context(char *buf, int buflen)
{
	int i = 0, copyLen = 0;
	char *pCur = buf, *pUrl = NULL;
	char strTmp[ONE_LINE_LEN+1], strUrl[URL_MAX_LEN];
	
	if(NULL == buf || buflen <= 0)
	{
		printf("Error:parse_url_from_http_context buf=NULL or len<=0\n");
		return -1;
	}
	
	while((pCur = strstr(pCur,URL_START_STR)) != NULL)
	{
		int offset = 5;

		memset(strTmp, 0x00, sizeof(strTmp));

		if (strlen(pCur) >= ONE_LINE_LEN)
		{
			copyLen = ONE_LINE_LEN;
		}
		else
		{
			copyLen = strlen(pCur);
		}
		
		memcpy(strTmp, pCur+URL_START_LEN, copyLen-URL_START_LEN);
		strTmp[copyLen-URL_START_LEN] = '\0';
		if (strstr(strTmp, "rmvb") != NULL)
		{
			printf("hhzzff rmvb=%s\n", strTmp);
			pCur += copyLen;
			continue;
		}
		pUrl = strstr(strTmp,".html");
		if(NULL == pUrl)
		{
			pUrl = strstr(strTmp, ".htm");
			offset = 4;
		}
		
		if(NULL != pUrl)
		{
			memset(strUrl, 0x00, sizeof(strUrl));
			memcpy(strUrl,strTmp, pUrl-strTmp+offset);
			if(queue_find(&g_QueueComplete, strUrl) == 1)
			{
				;//printf("This URL already processed\n");
			}
			else
			{
				char strFullUrl[URL_MAX_LEN] ="";
				memset(strFullUrl, 0x00, sizeof(strFullUrl));

				if(strncmp(strUrl, HTTP_START_STR, strlen(HTTP_START_STR)) != 0)
				{
					if (strUrl[0] != '/')
					{
						sprintf(strFullUrl, "%s%s%c%s", HTTP_START_STR, g_strCurHost, '/', strUrl);
					}
					else
					{
						sprintf(strFullUrl, "%s%s%s", HTTP_START_STR, g_strCurHost, strUrl);
					}
				}
				else
				{
					strcpy(strFullUrl, strUrl);
				}
				queue_en(&g_QueueProcess, strFullUrl);
			}
			pCur += copyLen;
		}
		else
		{
			pCur += copyLen;
		}
	}

	return 0;
}

int wsa_starup()
{
	WORD wVersion = MAKEWORD(2,2);
	WSADATA wsaData;

	return WSAStartup(wVersion, &wsaData);
}

int send_http_request(SOCKET s, char *srvIp, char *pHost, char *file)
{
	int ret = 0;
	char buff[1024] = {0};
	sprintf(buff, "GET %s HTTP/1.1\r\n"
		"Host: %s\r\n"
		"User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:6.0.1) Gecko/20100101 Firefox/6.0.1\r\n"
		"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
		"Accept-Language: zh-cn,en-us;q=0.7,en;q=0.3\r\n"
#if 0
		"Accept-Encoding: gzip, deflate\r\n"
#endif
		"Accept-Charset: UTF-8,*\r\n"
		"Connection: keep-alive\r\n\r\n", file, pHost);

	ret = send(s, buff, strlen(buff), 0);

	return ret;
}

int find_http_header_end(unsigned char *buf, unsigned int buflen, encode_type_t *encode)
{
	unsigned int i = 0;

	if(NULL == buf || NULL == encode)
		return -1;

	*encode = ENCODE_NONE;
	
	for(i=0; i<buflen-4; i++)
	{
		/* HTTP header end with \r\n\r\n */
		if(buf[i] == 0x0d && buf[i+1] == 0x0a && buf[i+2] == 0x0d && buf[i+3] == 0x0a)
		{
			if(strstr(buf, "Encoding:") != NULL)
			{
				*encode = ENCODE_GZIP;
			}
			
			return i;
		}
	}

	return -1;
}

int get_http_response(SOCKET s, char *file)
{
	BOOL bHandled = FALSE; /* HTTP header is handled or not */
	encode_type_t encodeType = ENCODE_NONE; /* Is the content Encoding or not */
	int iBodyOffset = 0;
	int ret = 0;
	FILE *pf = NULL;
	char buff[MAX_PACKET_SIZE+1] = {0};

#ifdef SAVE_FILE
	if( (NULL == file) || ((pf = fopen(file, "wb")) == NULL) )
	{
		return -1;
	}
#endif

	do 
	{
		memset(buff, 0x00, sizeof(buff));
		ret = recv(s, buff, MAX_PACKET_SIZE, 0);

		if(ret > 0)
		{
			//printf("\nbuff begin:\n%s\nbuff end\n", buff);
			parse_url_from_http_context(buff, ret);

			if(!bHandled)
			{
				iBodyOffset = find_http_header_end(buff, ret, &encodeType);
				if(iBodyOffset != -1) /* skip HTTP header*/
				{
					bHandled = TRUE;
#ifdef SAVE_FILE
					fwrite(buff+iBodyOffset, ret-iBodyOffset, 1, pf);
#endif
				}
#ifdef SAVE_FILE
				else
				{
					fwrite(buff, ret, 1, pf);
				}
#endif
			}
#ifdef SAVE_FILE
			else
			{
				fwrite(buff, ret, 1, pf);
			}
#endif

			if(encodeType != ENCODE_NONE)
			{
				printf("\nhzftest Encode:Gzip\n");
			}
		}
	} while (ret > 0);

#ifdef SAVE_FILE
	fclose(pf);
#endif
	return 0;
}
#if 1
int main(int argc, char *argv[])
{
	char s1[] = "bcd";
	char s2[] = "ebc";
	char plcs[LCS_STR_LEN+1] = "";

	lcs(s1, s2, plcs);
	printf("plcs=%s;\n");
	
	return 0;
}
#else
int main(int argc, char *argv[])
{
	SOCKET s = 0;
	struct sockaddr_in srvAddr;
	struct hostent *pSrvHost = NULL;
	char strUrl[URL_MAX_LEN] = "";
	char strHost[HOST_MAX_LEN] = "";
	char strPath[PATH_MAX_LEN] = "";
	char strSaveFile[FILE_NAME_MAX_LEN] = "";
	int ret = 0;
	int i = 0;
	int count = 0;
	FILE *fp = NULL;
	char * pStartURL = "http://www.piaohua.com/html/juqing/2010/0721/18967.html"; /* The first URL start from */

	ret = wsa_starup();
	if(ret != 0)
	{
		printf("WSAStartup fail, error=%s\n", strerror(WSAGetLastError()));
		exit(-1);
	}

	queue_init(&g_QueueComplete);
	queue_init(&g_QueueProcess);
	queue_en(&g_QueueProcess, pStartURL);

	memset(&srvAddr, 0x00, sizeof(srvAddr));
	srvAddr.sin_family = AF_INET;
	srvAddr.sin_port = htons(80);

	while(queue_empty(&g_QueueProcess) != 1)
	{
		ret = queue_de(&g_QueueProcess, strUrl);
		if(ret != 0)
		{
			continue;
		}
		printf("\n\ncount=%d,strUrl=%s\n\n", count, strUrl);

		memset(strHost, 0x00, sizeof(strHost));
		memset(strPath, 0x00, sizeof(strPath));
		ret = split_url_to_host_path(strUrl, strHost, strPath);
		if(ret != 0)
		{
			continue;
		}

		pSrvHost = gethostbyname(strHost);
		if(NULL == pSrvHost)
		{
			printf("gethostbyname fail\n");
			continue;
		}
		memcpy(&srvAddr.sin_addr, pSrvHost->h_addr_list[0], pSrvHost->h_length);

		memset(g_strCurHost, 0x00, sizeof(g_strCurHost));
		strcpy(g_strCurHost, strHost);

		s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if(s < 0)
		{
			printf("socket fail, error=%s\n", strerror(WSAGetLastError()));
			exit(-1);
		}
		
		ret = connect(s, (struct sockaddr *)&srvAddr, sizeof(srvAddr));
		if(ret != 0)
		{
			printf("connect fail, error=%s\n", strerror(WSAGetLastError()));
			closesocket(s);
			continue;
		}
		
		ret = send_http_request(s, inet_ntoa(srvAddr.sin_addr), strHost, strPath);
		if(SOCKET_ERROR == ret)
		{
			printf("sendto fail, error=%s\n", strerror(WSAGetLastError()));
			closesocket(s);
			continue;
		}

#ifdef SAVE_FILE		
		ret = generate_filename_for_save(strPath, strSaveFile);

		if(ret != 0)
		{
			sprintf(strSaveFile,"view_%d.htm", count);
		}

		if((fp = fopen(strSaveFile, "rb")) != NULL)
		{
			printf("save file already exist\n");
			fclose(fp);
			closesocket(s);
			continue;
		}
#endif
		queue_en(&g_QueueComplete, strUrl);

		ret = get_http_response(s, strSaveFile);
		
		closesocket(s);

		if(++count >= 120)
		{
			printf("break:finish search %d\n", count);
			break;
		}
	}

	WSACleanup();

	return 0;
}
#endif
